<!--
 * @Author: Li Zengkun
 * @Date: 2022-09-06 16:00:55
 * @LastEditors: Li Zengkun
 * @LastEditTime: 2022-09-06 23:27:29
 * @Description: 数据穿梭框
-->
<template>
  <div>
    <a-breadcrumb>
      <a-breadcrumb-item>Vue 练习</a-breadcrumb-item>
      <a-breadcrumb-item>1.数据穿梭框</a-breadcrumb-item>
    </a-breadcrumb>
    <div class="artical-content">
      <h1>数据穿梭框</h1>
      <UserCard />
      <a-divider></a-divider>
      <h2>样例:</h2>
      <a-transfer
        :data="data"
        :default-value="value"
        :title="['列表1', '列表2']"
      />
      <a-divider></a-divider>
      <h2>实现:</h2>
      <a-row style="overflow: hidden; position: relative; height: 242px">
        <!-- 左边列表框 -->
        <a-col class="list-box" :span="5">
          <div class="header">
            <label for="list1All">
              <input
                id="list1All"
                type="checkbox"
                :checked="isAllPush"
                :disabled="isAllPushDisabled"
                @click="onAllPush"
              />
              列表1
            </label>
            <span>{{ needPush.length }} / {{ notSelectLength }}</span>
          </div>
          <ul class="list">
            <li
              v-for="(item, index) of notSelect"
              :key="index"
              @click.prevent="onPushSelect(item.value)"
            >
              <input type="checkbox" :checked="needPush.includes(item.value)" />
              {{ item.label }}
            </li>
          </ul>
        </a-col>

        <!-- 操作按钮 -->
        <a-col :span="2" class="btn-box">
          <a-button
            @click.prevent="push"
            type="primary"
            shape="circle"
            :disabled="needPush.length === 0"
          >
            <icon-right />
          </a-button>
          <a-button
            @click.prevent="pull"
            :disabled="needPull.length === 0"
            type="primary"
            shape="circle"
          >
            <icon-left />
          </a-button>
        </a-col>

        <!-- 右边列表框 -->
        <a-col class="list-box" :span="5">
          <div class="header">
            <label for="list2All">
              <input
                id="list2All"
                type="checkbox"
                :checked="isAllPull"
                :disabled="isAllPullDisabled"
                @click="onAllPull"
              />
              列表2
            </label>
            <span>{{ needPull.length }} / {{ selected.length }}</span>
          </div>
          <ul class="list">
            <li
              v-for="(item, index) in hasSelected"
              :key="index"
              @click.stop.prevent="onPullSelect(item.value)"
            >
              <input type="checkbox" :checked="needPull.includes(item.value)" />
              {{ item.label }}
            </li>
          </ul>
        </a-col>
      </a-row>
      <h2>代码:</h2>
      <h3>HTML 部分:</h3>
      <pre><code class='language-html line-numbers'>{{codehtml}}</code></pre>
      <h3>JS 部分:</h3>
      <pre><code class='language-javascript line-numbers'>{{code}}</code></pre>
    </div>
  </div>
</template>
 
<script setup>
import { ref, reactive, computed, onMounted } from "vue";
import { Message } from "@arco-design/web-vue";
import UserCard from "@/components/UserCard.vue";
import Prism from "prismjs";

const res = reactive({
   name:'lzk',
   age:22,
})
console.log(res);

onMounted(() => {
  Prism.highlightAll();
});

// ---------------- 样例 Start --------------------
const data = Array(8)
  .fill(undefined)
  .map((_, index) => ({
    value: `option${index + 1}`,
    label: `Option ${index + 1}`,
  }));
const value = ["option1", "option3", "option5"];
// ---------------- 样例 End --------------------




// ----------------- 实现 Start --------------------
// 已经选中的 options.value 数组
const selected = ref(["option1", "option2", "option3"]);
// 左边 选中的由 data.value 组成的数组
const needPush = ref([]);
const needPull = ref([]);

// 左边 点击每一个选项触发的事件
const onPushSelect = (value) => {
  // 判断是否已选中
  let index = needPush.value.indexOf(value);

  if (index === -1) {
    //如果之前没有选中,那么现在选中push到 needPush 中
    needPush.value.push(value);
  } else {
    //如果选中则取消选中
    needPush.value.splice(index, 1);
  }
};
// 计算属性: 监听 左边 所有的选项 options对象数组
const notSelect = computed({
  get() {
    return data.filter((item, i) => {
      return selected.value.indexOf(item.value) === -1;
    });
  },
});
// 把选项从 左边 挪到 右边 的按钮点击事件
const push = () => {
  needPush.value.forEach((item) => {
    selected.value.push(item);
  });
  needPush.value = [];
  Message.success("Push success!");
};
// 计算属性: 左边 所有选项个数
const notSelectLength = computed(() => {
  return data.length - selected.value.length;
});
// 计算属性: 判断 左边 是否全部选中
const isAllPush = computed(() => {
  if (notSelectLength.value === 0) return false;
  return needPush.value.length === notSelectLength.value;
});
// 计算属性: 判断 左边 notSelectLength 是否为0;以此来禁用全选按钮
const isAllPushDisabled = computed(() => {
  if (notSelectLength.value === 0) return true;
  return false;
});
// 左边 全选按钮点击事件
const onAllPush = () => {
  if (needPush.value.length != notSelectLength.value) {
    needPush.value = [];
    notSelect.value.forEach((item) => {
      needPush.value.push(item.value);
    });
  } else {
    needPush.value = [];
  }
};

const onPullSelect = (value) => {
  let index = needPull.value.indexOf(value);

  if (index === -1) {
    needPull.value.push(value);
  } else {
    needPull.value.splice(index, 1);
  }
  console.log(needPull);
};
const hasSelected = computed({
  get() {
    return data.filter((item, i) => {
      return selected.value.indexOf(item.value) !== -1;
    });
  },
});
const pull = () => {
  needPull.value.forEach((item, index) => {
    let needDeleteIndex = selected.value.indexOf(item);
    selected.value.splice(needDeleteIndex, 1);
  });
  needPull.value = [];
  Message.success("Pull success!");
};
const isAllPull = computed(() => {
  if (selected.value.length === 0) return false;
  return needPull.value.length === selected.value.length;
});
const isAllPullDisabled = computed(() => {
  if (selected.value.length === 0) return true;
  return false;
});
const onAllPull = () => {
  if (needPull.value.length != selected.value.length) {
    needPull.value = [];
    hasSelected.value.forEach((item) => {
      needPull.value.push(item.value);
    });
  } else {
    needPull.value = [];
  }
};
// ----------------- 实现 End --------------------

// ____________________ 代码 ________________
const codehtml = ref(`
<template>
   <a-row style="overflow: hidden; position: relative; height: 242px">
     <!-- 左边列表框 -->
     <a-col class="list-box" :span="5">
       <div class="header">
         <label for="list1All">
           <input
             id="list1All"
             type="checkbox"
             :checked="isAllPush"
             :disabled="isAllPushDisabled"
             @click="onAllPush"
           />
           列表1
         </label>
         <span>{{ needPush.length }} / {{ notSelectLength }}</span>
       </div>
       <ul class="list">
         <li
           v-for="(item, index) of notSelect"
           :key="index"
           @click.prevent="onPushSelect(item.value)"
         >
           <input type="checkbox" :checked="needPush.includes(item.value)" />
           {{ item.label }}
         </li>
       </ul>
     </a-col>
     <!-- 操作按钮 -->
     <a-col :span="2" class="btn-box">
       <a-button
         @click.prevent="push"
         type="primary"
         shape="circle"
         :disabled="needPush.length === 0"
       >
         <icon-right />
       </a-button>
       <a-button
         @click.prevent="pull"
         :disabled="needPull.length === 0"
         type="primary"
         shape="circle"
       >
         <icon-left />
       </a-button>
     </a-col>
     <!-- 右边列表框 -->
     <a-col class="list-box" :span="5">
       <div class="header">
         <label for="list2All">
           <input
             id="list2All"
             type="checkbox"
             :checked="isAllPull"
             :disabled="isAllPullDisabled"
             @click="onAllPull"
           />
           列表2
         </label>
         <span>{{ needPull.length }} / {{ selected.length }}</span>
       </div>
       <ul class="list">
         <li
           v-for="(item, index) in hasSelected"
           :key="index"
           @click.stop.prevent="onPullSelect(item.value)"
         >
           <input type="checkbox" :checked="needPull.includes(item.value)" />
           {{ item.label }}
         </li>
       </ul>
     </a-col>
   </a-row>
</template>
`)
const code = ref(`
<script setup>
import { ref, reactive, computed } from "vue";
import { Message } from "@arco-design/web-vue";

// 初始化所有选项 options
const data = Array(8)
  .fill(undefined)
  .map((_, index) => ({
    value: 'option' + index + 1',
    label: 'Option ' + index + 1',
  }));

// 已经选中的 options.value 数组
const selected = ref(["option1", "option2", "option3"]);

// 左边 选中的由 data.value 组成的数组
const needPush = ref([]);
const needPull = ref([]);

// 左边 点击每一个选项触发的事件
const onPushSelect = (value) => {
  // 判断是否已选中
  let index = needPush.value.indexOf(value);

  if (index === -1) {
    //如果之前没有选中,那么现在选中push到 needPush 中
    needPush.value.push(value);
  } else {
    //如果选中则取消选中
    needPush.value.splice(index, 1);
  }
};

// 计算属性: 监听 左边 所有的选项 options对象数组
const notSelect = computed({
  get() {
    return data.filter((item, i) => {
      return selected.value.indexOf(item.value) === -1;
    });
  },
});

// 把选项从 左边 挪到 右边 的按钮点击事件
const push = () => {
  needPush.value.forEach((item) => {
    selected.value.push(item);
  });
  needPush.value = [];
  Message.success("Push success!");
};

// 计算属性: 左边 所有选项个数
const notSelectLength = computed(() => {
  return data.length - selected.value.length;
});

// 计算属性: 判断 左边 是否全部选中
const isAllPush = computed(() => {
  if (notSelectLength.value === 0) return false;
  return needPush.value.length === notSelectLength.value;
});

// 计算属性: 判断 左边 notSelectLength 是否为0;以此来禁用全选按钮
const isAllPushDisabled = computed(() => {
  if (notSelectLength.value === 0) return true;
  return false;
});

// 左边 全选按钮点击事件
const onAllPush = () => {
  if (needPush.value.length != notSelectLength.value) {
    needPush.value = [];
    notSelect.value.forEach((item) => {
      needPush.value.push(item.value);
    });
  } else {
    needPush.value = [];
  }
};

// ---------------------- 右边穿梭框操作 同上 ----------------------------
const onPullSelect = (value) => {
  let index = needPull.value.indexOf(value);

  if (index === -1) {
    needPull.value.push(value);
  } else {
    needPull.value.splice(index, 1);
  }
  console.log(needPull);
};
const hasSelected = computed({
  get() {
    return data.filter((item, i) => {
      return selected.value.indexOf(item.value) !== -1;
    });
  },
});
const pull = () => {
  needPull.value.forEach((item, index) => {
    let needDeleteIndex = selected.value.indexOf(item);
    selected.value.splice(needDeleteIndex, 1);
  });
  needPull.value = [];
  Message.success("Pull success!");
};
const isAllPull = computed(() => {
  if (selected.value.length === 0) return false;
  return needPull.value.length === selected.value.length;
});
const isAllPullDisabled = computed(() => {
  if (selected.value.length === 0) return true;
  return false;
});
const onAllPull = () => {
  if (needPull.value.length != selected.value.length) {
    needPull.value = [];
    hasSelected.value.forEach((item) => {
      needPull.value.push(item.value);
    });
  } else {
    needPull.value = [];
  }
};
`);
</script>

<style lang='less' scoped>
.list-box {
  border: 1px solid var(--color-neutral-3);
  position: relative;
  .header {
    position: absolute;
    top: 0;
    width: 100%;
    display: flex;
    justify-content: space-between;
    padding: 0 10px;
    line-height: 40px;
    background: var(--color-neutral-1);
    box-sizing: border-box;
    span {
      color: var(--color-neutral-6);
      font-size: 13px;
    }
  }
  .list {
    list-style-type: none;
    position: relative;
    //   background: red;
    height: 200px;
    margin: 40px 0 0 0;
    padding: 0;
    overflow: auto;
    li {
      width: 100%;
      text-align: left;
      padding: 0 10px;
      box-sizing: border-box;
      line-height: 40px;
      &:hover {
        background: var(--color-neutral-2);
      }
    }
  }
}
.btn-box {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  flex-direction: column;
  gap: 10px;
}
</style>